<!-- 通过凭证和地址上传视频或图片 -->
<template>

  <template v-if="props.type==='video'">
    <div class="video-box" @click="videoFn.handleUpload">
      <input ref="uploadVideoInput" class="upload-input" type="file" accept="video/*" @change="videoFn.fileChange">
      <el-icon class="upload-icon"><upload-filled /></el-icon>
      <p class="upload-text">点击选择视频</p>
      <div class="video-player" v-if="video.preUrl" @click.stop>
        <videoPlayer :src="video.preUrl" get-info get-cover @info="videoFn.infoBack"  @cover="videoFn.coverBack"></videoPlayer>
        <el-icon class="remove-icon" @click="videoFn.removeVideo"><delete /></el-icon>
      </div>
    </div>
    <div :class="['cover-box',video.preUrl?'cover-box-show':'']">
      <input ref="uploadCoverInput" class="upload-input" type="file" accept="image/*" @change="videoFn.coverFileChange">
      <div class="image-viewer" >
        <el-image class="image" :src="video.coverUrl" fit="contain" @click="openImageViewer([video.coverUrl],0)"></el-image>
        <el-icon class="change-icon" @click="videoFn.handleUploadCover"><refresh /></el-icon>
        <!-- <el-icon class="remove-icon" @click="videoFn.removeCover"><delete /></el-icon> -->
      </div>
    </div>
  </template>

  <template v-else-if="props.type==='image'">
    <div class="image-panel" @click.stop>
      <div class="image-viewer" v-for="(url,index) in image.preUrls||[]" :key="index">
        <el-image class="image" :src="url" fit="contain" @click="openImageViewer(image.preUrls,index)">
        </el-image>
        <el-icon class="remove-icon" @click="imageFn.removeImage(index)"><delete /></el-icon>
      </div>
    </div>
    <div class="image-box" @click="imageFn.handleUpload">
      <input ref="uploadImageInput" class="upload-input" type="file" accept="image/*" @change="imageFn.fileChange" multiple>
      <el-icon class="upload-icon"><upload-filled /></el-icon>
      <p class="upload-text">点击选择图片</p>
    </div>
    <!-- <p v-else class="process-ingo">{{aliyun.statusText}} {{aliyun.authProgress}}</p> -->
  </template>

</template>

<script setup>
import { reactive, ref, watchEffect } from 'vue';
import { UploadFilled,Delete,Refresh } from '@element-plus/icons-vue'
import videoPlayer from "@/components/video/videoPlayer"
import { ElMessage } from 'element-plus';
import {getVodUploadAuth,refreshVodUploadAuth,getImageUploadAuth,getRegionAuth} from "@/api/operation";
import imageViewer from "@/components/imageViewer/index2";
const props = defineProps({
  type: {
    default: "video",//"video"||"image"
    type: String,
  },
  uploadStatus: {
    default: "",//""||"uoload"||"clear",当状态变为upload时，触发上传;为clear时，清空数据
    type: String,
  }
})
const emit = defineEmits([
  "video:info","image:info",
  "video:ready","image:ready",
  "video:success","image:success",
  "video:fail","image:fail",
  "video:progress","image:progress",
  "update:uploadStatus",
  "clear"
])
const uploadVideoInput = ref(null);
const uploadImageInput = ref(null);
const uploadCoverInput = ref(null);

const {$data:aliyun,$fn:aliyunFn,backup:aliyun2} = (()=>{
  const backup={
    region: "cn-beijing",
    userId: "1183416238947919",//固定
    videoId: "",
    imageId: "",

    uploader: null,

    uploadBack:[],//上传多文件时，将所有结果打包返回
    uploaderImages: [],
    infoImages:[],//图片的尺寸数据，与uploaderImages一一对应
  }
  const $data = reactive({
    statusText:"",
    authProgress:"",
    title:"",
    fileName:"",
  })
  const $fn={
    createUploader (type="video",imageType="default",index) {
      /**
       * type: "image"||"video"
       * imageType: "default"||"cover",当type==="image"时存在
       * index: number,当inageType==="default"时,图片的序号，用于拼接数据
       * */ 
      const uploader = new AliyunUpload.Vod({
        timeout: 60000,
        partSize: 1048576,
        parallel: 5,
        retryCount: 3,
        retryDuration: 2,
        region: backup.region,
        userId: backup.userId,
        // 添加文件成功
        addFileSuccess(uploadInfo) {
          // console.log("添加文件成功:",uploadInfo);
          $data.statusText = '添加文件成功, 等待上传...';
          if(type==="image"){//返回准备上传的图片数量
            emit(type+":ready",backup.uploaderImages.length);
          }else{
            emit(type+":ready",1);
          }
          
        },
        // 开始上传
        onUploadstarted(uploadInfo) {
          // console.log("开始上传：",uploadInfo);
          let setVideoAuth = (res)=>{
            let {uploadAuth,uploadAddress,videoId} = res.data;
            uploader.setUploadAuthAndAddress(uploadInfo, uploadAuth, uploadAddress, videoId);
          }
          let setImageAuth = (res)=>{
            let {uploadAuth,uploadAddress,imageId,imageURL} = res.data;
            uploader.setUploadAuthAndAddress(uploadInfo, uploadAuth, uploadAddress,imageId);
            backup.infoImages[index] = {
              ...(backup.infoImages[index]||{}),
              imageId,
              imageUrl:imageURL,
            }
          }
          if(type==="video"){
            if(!backup.videoId && !uploadInfo.videoId){
              getVodUploadAuth({title:aliyun.title,fileName:aliyun.fileName}).then(setVideoAuth);
            }else{
              refreshVodUploadAuth({videoId:uploadInfo.videoId}).then(setVideoAuth);
            }
          }else{
            // if(imageType!=="cover"){
            getImageUploadAuth({imageType}).then(setImageAuth);
            // }
          }
        },
        // 文件上传成功
        onUploadSucceed (uploadInfo) {
          // console.log("**********上传成功：",uploadInfo);
          $data.statusText = '文件上传成功!';
          // emit(type+":success",uploadInfo);
          if(type==="video"){
            backup.uploadBack.push(uploadInfo);
            if(backup.uploadBack.length===2){
              emit("video:success",[...backup.uploadBack]);
            }
          }else{
            if(imageType==="cover"){//封面单图片
              backup.uploadBack.push(uploadInfo);
              if(backup.uploadBack.length===2){
                emit("video:success",[...backup.uploadBack]);
              }
            }else{//默认图片
              backup.uploadBack.push({...backup.infoImages[index],...uploadInfo,_index:index});
              if(backup.uploadBack.length===backup.uploaderImages.length){
                emit("image:success",[...backup.uploadBack]);
              }
            }
          }
        },
        // 文件上传失败
        onUploadFailed (uploadInfo, code, message) {
          $data.statusText = '文件上传失败!';
          emit(type+":fail",message);
        },
        // 取消文件上传
        onUploadCanceled (uploadInfo, code, message) {
          $data.statusText = '文件已暂停上传'
        },
        // 文件上传进度，单位：字节, 可以在这个函数中拿到上传进度并显示在页面上
        onUploadProgress (uploadInfo, totalSize, progress) {
          // console.log("文件上传进度:",progress);
          let progressPercent = Math.ceil(progress * 100);
          $data.authProgress = progressPercent;
          $data.statusText = '文件上传中...';
          if(imageType==="default"){
            emit(type+":progress",progress,index);
          }else{
            emit(type+":progress",progress);
          }
        },
        // 上传凭证超时
        onUploadTokenExpired (uploadInfo) {
          if(type==="video"){
            // 根据videoid刷新凭证
            refreshVodUploadAuth({videoId:uploadInfo.videoId}).then(res=>{
              if(res.code===0){
                let {uploadAuth} = res.data;
                uploader.resumeUploadWithAuth(uploadAuth)
              }
            })
          }else{
            getImageUploadAuth({imageType}).then(res=>{
              if(res.code===0){
                let {uploadAuth} = res.data;
                uploader.resumeUploadWithAuth(uploadAuth)
              }
            })
          }
            $data.statusText = '文件超时...';
        },
        // 全部文件上传结束
        onUploadEnd(uploadInfo) {
          // console.log("全部文件上传结束:",uploadInfo);
          $data.statusText = '文件上传完毕';
        },
      });
      return uploader;
    },
    clearUpload(){
      backup.uploadBack = [];//成功后返回
      $data.statusText = "";
      $data.authProgress = "";
      backup.uploader = null;
      backup.uploaderImages = [];
      backup.infoImages = [];
      $data.title = "";
      $data.fileName = "";
    }
  }
  getRegionAuth().then((res)=>{
    if(res.data?.regionId){
      backup.region = res.data.regionId;
    }
  });

  return {
    $data,
    $fn,
    backup,
  }
})();

// 视频上传
const {$fn: videoFn, $data: video} = (() => {
  const backup = {
    file:null,
  }
  const $data = reactive({
    preUrl: "",//视频预览地址
    coverUrl: "", //封面预览地址
    status: true,//状态，false即不合法
  })
  const $fn={
    handleUpload() {
      uploadVideoInput.value.click();
    },
    async fileChange(e) {
      const files = e.target.files||[];
      backup.file = files[0];
      if(backup.file.size > 10*1024*1024*1024){
        ElMessage.error("视频大小不能超过 10 Gb!");
        $data.status = false;
        return;
      }
      $data.status = true;

      if (!backup.file) return;
      // 1.生成预览的地址
      $data.preUrl = getObjectURL([backup.file])[0];
      // 1.将文件添加到aliyun SDK预备上传
      aliyun.title = backup.file.name.split(".")[0];
      aliyun.fileName = aliyun.title+Date.now()+".mp4";
      if (aliyun2.uploader) {
        aliyun2.uploader.stopUpload();
        aliyun.authProgress = 0;
        aliyun.statusText = "";
      }
      aliyun2.uploader = aliyunFn.createUploader();
      aliyun2.uploader.addFile(files[0], null, null, null, '{"Vod":{}}');
      
    },
    // 上传文件
    uploadStart(){
      if (aliyun2.uploader && $data.status) {
        aliyun2.uploader.startUpload();
        aliyun2.uploaderImages[0].startUpload();
      }
    },
    removeVideo(){
      $data.preUrl = "";//视频预览地址
      backup.file = null;//视频文件
      aliyun.authProgress = 0;//上传进度
      aliyun.statusText = "";//上传进程提示文字
      $data.status = true;//能否上传
      aliyun2.uploader = null;//aliyun上传对象
      $data.coverUrl = "";
      uploadVideoInput.value.value = "";
      uploadCoverInput.value.value = "";
      emit("video:ready",0);
      emit("image:info",false);
    },
    handleUploadCover(){
      uploadCoverInput.value.click();
    },
    coverFileChange(e) {
      let file = e.target.files[0];
      if(!file)return;
      // 1.生成预览的地址
      $data.coverUrl = getObjectURL([file])[0];
      // 2.将文件添加到aliyun SDK预备上传
      const image = document.createElement("img");
      image.addEventListener("load",(e)=>{
        aliyun2.infoImages[0] = {width:e.target.width,height:e.target.height};
      });
      // 将图片的url地址添加到图片地址中
      image.src = $data.coverUrl;
      
      emit("image:info",true);
      if(aliyun2.uploaderImages[0]){
        aliyun2.uploaderImages[0].cleanList();
      }else{
        aliyun2.uploaderImages[0] = aliyunFn.createUploader("image","cover");
      }
      aliyun2.uploaderImages[0].addFile(file, null, null, null, '{"Vod":{}}');
    },
    coverBack(file){
      console.log("cover file:",file);
      aliyun2.uploaderImages[0] = aliyunFn.createUploader("image","cover");
      aliyun2.uploaderImages[0].addFile(file, null, null, null, '{"Vod":{}}');
      $data.coverUrl = getObjectURL([file])[0];
      emit("image:info",true);
    },
    infoBack(info){
      if(info.duration >= 10*60){
        ElMessage.error("视频时长不能超过 10 min!");
        $data.status = false;
        return;
      }
      $data.status = true;
      emit("video:info",{...info,size:backup.file.size});
    },
    clearUpload(){
      $fn.removeVideo();
      aliyunFn.clearUpload();
      emit("update:uploadStatus","");
      emit("clear");
    }
  }
  return {
    $data,
    $fn,
  }
})();

// 图片上传
const {$fn: imageFn, $data: image} = (() => {
  const $data = reactive({
    preUrls: [],
    status: true,//状态，false即不合法
  })
  const $fn={
    handleUpload() {
      uploadImageInput.value.click();
    },
    fileChange(e) {
      let files = Array.from(e.target.files||[]);
      if (files.length===0) return;
      if(files.length>9){
        ElMessage.warning("图片数量不能超过 9 张！已自动截取前9张。")
        files = files.splice(0,9);
      }
      // 1.生成预览的地址
      $data.preUrls = getObjectURL(files);
      // 2.将文件添加到aliyun SDK预备上传
      for(let i=0,len=files.length;i<len;i++){
        let file = files[i];
        const image = document.createElement("img");
        image.addEventListener("load",(e)=>{
          aliyun2.infoImages[i] = {width:e.target.width,height:e.target.height};
        });
        // 将图片的url地址添加到图片地址中
        image.src = $data.preUrls[i];
        aliyun2.uploaderImages[i] = aliyunFn.createUploader("image","default",i);
        aliyun2.uploaderImages[i].addFile(file, null, null, null, '{"Vod":{}}');
      }
    },
    // 上传文件
    uploadStart(){
      // console.log("开始上传文件！",aliyun2.uploaderImages);
      for(let uploader of aliyun2.uploaderImages){
        uploader.startUpload();
      }
    },
    removeImage(index){
      aliyun2.uploaderImages?.splice(index,1);
      aliyun2.infoImages?.splice(index,1);
      aliyun2.uploadBack?.splice(index,1);
      $data.preUrls?.splice(index,1);
      emit("image:ready",aliyun2.uploaderImages.length);
    },
    
    clearUpload(){
      aliyunFn.clearUpload();
      $data.preUrls = [];
      $data.status = true;
      emit("update:uploadStatus","");
      emit("clear");
    }
  }
  return {
    $data,
    $fn,
  }
})();


watchEffect(()=>{
  if(props.uploadStatus === "upload"){
    if(props.type==="video"){
      videoFn.uploadStart();
    }else{
      imageFn.uploadStart();
    }
  }else if(props.uploadStatus==="clear"){
    if(props.type==="video"){
      videoFn.clearUpload();
    }else{
      imageFn.clearUpload();
    }
  }
})

function getObjectURL(files) {
  let res = [];
  for(let file of files||[]){
    let url = null;
    if (window.createObjectURL != undefined) { // basic
      url = window.createObjectURL(file);
    } else if (window.URL != undefined) { // mozilla(firefox)
      url = window.URL.createObjectURL(file);
    } else if (window.webkitURL != undefined) { // webkit or chrome
      url = window.webkitURL.createObjectURL(file);
    }
    res.push(url);
  }
  return res;
}
function openImageViewer(list,index){
  let imageUrl = list?.[0]||null;
  if(!imageUrl){return;}
  imageViewer({initialIndex: index,urlList: list});
}
</script>

<style scoped lang="scss">
@mixin removeBtn(){
  position: absolute;
  right: 12px;
  top: 12px;
  width: 24px;
  height: 24px;
  color: #ffffff;
  border-radius: 50%;
  cursor: pointer;
  background-color: rgba(0, 0, 0, 0.3);
  &:hover{
    background-color: rgba(0, 0, 0, 0.5);
  }
}
.video-box,.image-box{
  vertical-align: top;
  position: relative;
  color: rgb(133, 133, 133);
  border: 1px dashed rgb(133, 133, 133);
  background-color: #ffffff;
  border-radius: 8px;
  display: inline-block;
  text-align: center;
  cursor: pointer;
  &:hover{
    color: #1890FF;
    border-color: #1890FF;
  }
  .upload-input {
    display: none;
    z-index: -1;
  }
  .upload-icon{
    display: block;
    width: 100%;
    font-size: 36px;
  }
  .upload-text{
    margin: 8px 0;
  }
}

.video-box{
  width: 320px;
  height: 320px;
  margin-right: 24px;
  .video-player{
    position: absolute;
    top: 0;
    left: 0;
    .remove-icon{
      @include removeBtn();
    }
  }
  .upload-icon{
    margin-top: 120px;
  }
}
.cover-box{
  display: none;
  >*{
    vertical-align: top;
  }
  .label{
    margin-right: 8px;
    color: #606266;
  }
  .upload-input {
    display: none;
    z-index: -1;
  }
  .image-viewer{
    display: inline-block;
    position: relative;
    .change-icon{
      @include removeBtn();
    }
    .image{
      width:320px;
      height:320px;
      background-color:#f5f7fa;
    }
  }
  &.cover-box-show{
    display: inline-block;
  }
}
.image-box{
  width: 160px;
  height: 160px;
  .upload-icon{
    margin-top: 40px;
  }
}
.image-panel{
  display: inline-block;
  .image-viewer{
    display: inline-block;
    position: relative;
    .remove-icon{
      @include removeBtn();
    }
    .image{
      width: 160px;
      height: 160px;
      margin: 0 8px;
      background-color: #f0f2f5;
      border-radius: 8px;
    }
  }
}
</style>